import { isFunction } from './utils'
import { createPrivateName } from './shared';
import { CurrentInstance, getCurrentInstance } from './instance'

// properties（props传值）
// data（值）
// observers（字段监听器）
// methods(方法)
// 组件的钩子函数

export enum ComponentLifecycle {
	CREATED = 'created',
	ATTACHED = 'attached',
	READY = 'ready',
	MOVED = 'moved',
	DETACHED = 'detached'

	// show
	// hide
	// resize

	// properties
	// data
	// observers
	// methods
	// options

	// behaviors
	// relations
	// externalClasses
	// lifetimes
	// pageLifetimes
	// definitionFilter
}
// 小程序的钩子函数
export enum PageLifecycle {
	LOAD = 'onLoad',
	SHOW = 'onShow',
	READY = 'onReady',
	HIDE = 'onHide',
	UNLOAD = 'onUnload',
	PULL_DOWN_REFRESH = 'onPullDownRefresh',
	REACH_BOTTOM = 'onReachBottom',
	SHARE_APP_MESSAGE = 'onShareAppMessage',
	SHARE_TIME_LINE = 'onShareTimeLine',
	ADD_TO_FAVORITES = 'onAddToFavorites',
	PAGE_SCROLL = 'onPageScroll',
	RESIZE = 'onResize',
	TAB_ITEM_TAP = 'onTabItemTap',
}

/** 
 * 创建钩子
 * @param lifecycle {PageLifecycle|ComponentLifecycle} 生命周期
 * @return {Function} 返回钩子函数
 */
function createHook(
	lifecycle: ComponentLifecycle | PageLifecycle,
): (callback: Function) => void {
	return (callback: Function): void => {
		let currentInstance = getCurrentInstance();
		currentInstance && injectHook.call(currentInstance, lifecycle, callback)
	}
}

/** 
 * 注入 hooks
 * @param lifecycle {PageLifecycle|ComponentLifecycle} 生命周期
 * @param hook {Function} 注入的hook
 */
function injectHook(
	this: CurrentInstance,
	lifecycle: PageLifecycle | ComponentLifecycle,
	hook: Function
) {
	const privateName = createPrivateName(lifecycle as string);
	this[privateName] === undefined && (this[privateName] = [])
	this[privateName].push(hook) // 添加hook
}

/** 
 * 执行 hooks
 * @param lifecycle {PageLifecycle|ComponentLifecycle} 生命周期
 * @param params {any[]} 执行的参数
 * @return {any[]} 所有方法执行返回的值
 */
function conductHook(
	this: CurrentInstance,
	lifecycle: PageLifecycle | ComponentLifecycle,
	params: any[]
): any[] {
	const privateName = createPrivateName(lifecycle as string)
	const injectLifes: Function[] = this[privateName] || []
	return injectLifes.map(life => isFunction(life) && life.apply(this, params))
}

/** 
 * 创建生命周期
 * @param lifecycle {PageLifecycle|ComponentLifecycle} 生命周期
 * @param options {PlainObject} 参数
 * @return {Function} 返回生命周期执行函数
 */
export function createLifecycleMethods(
	lifecycle: PageLifecycle | ComponentLifecycle,
	options: Record<string, any>
): Function {
	const lifecycleMethod = options[lifecycle]; // options中的生命周期
	return function (this: CurrentInstance, ...args: any[]): any[] {
		let injectLifes = conductHook.call(this, lifecycle, args) // 执行hooks
		lifecycleMethod && injectLifes.push(lifecycleMethod.apply(this, args))
		// 返回值，适应分享等钩子
		return injectLifes
	}
}

// 组件钩子
export const created = createHook(ComponentLifecycle.CREATED)
export const attached = createHook(ComponentLifecycle.ATTACHED)
export const ready = createHook(ComponentLifecycle.READY)
export const moved = createHook(ComponentLifecycle.MOVED)
export const detached = createHook(ComponentLifecycle.DETACHED)

// 页面钩子
export const onLoad = createHook(PageLifecycle.LOAD)
export const onShow = createHook(PageLifecycle.SHOW)
export const onReady = createHook(PageLifecycle.READY)
export const onHide = createHook(PageLifecycle.HIDE)
export const onUnload = createHook(PageLifecycle.UNLOAD)
export const onPullDownRefresh = createHook(PageLifecycle.PULL_DOWN_REFRESH)
export const onReachBottom = createHook(PageLifecycle.REACH_BOTTOM)
export const onShareAppMessage = createHook(PageLifecycle.SHARE_APP_MESSAGE)
export const onShareTimeLine = createHook(PageLifecycle.SHARE_TIME_LINE)
export const onAddToFavorites = createHook(PageLifecycle.ADD_TO_FAVORITES)
export const onPageScroll = createHook(PageLifecycle.PAGE_SCROLL)
export const onResize = createHook(PageLifecycle.RESIZE)
export const onTabItemTap = createHook(PageLifecycle.TAB_ITEM_TAP)